//
//  NSObject+KVO.m
//  KnowledgeHierarchy
//
//  Created by linyi on 2020/4/11.
//  Copyright © 2020年 linyi. All rights reserved.
//

/*
NSKeyValueObservingOptionNew        返回新值
NSKeyValueObservingOptionOld        返回旧值
NSKeyValueObservingOptionInitial    注册时发一次通知，改变的时候也会发送通知
NSKeyValueObservingOptionPrior      改变前发一次，改变后发一次
 */

#import "NSObject+KVO.h"
#import <objc/message.h>
#import <objc/runtime.h>
@implementation NSObject (KVO)

- (void)LY_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context{
    // 1.动态添加一个类
    // 1.1 拿到原类名，拼接新的类名
    NSString *oldClassName = NSStringFromClass([self class]);
    NSString *newClassName = [@"LYKVO" stringByAppendingString:oldClassName];
    // 1.2转成C字符串
    const char *names = [newClassName UTF8String];
    // 1.3定义一个类
    Class myClass = objc_allocateClassPair([self class], names, 0);
    // 1.4注册类
    objc_registerClassPair(myClass);
    // 2.添加set方法
    NSString *setKeyPathsString = [NSString stringWithFormat:@"set%@:",[keyPath capitalizedString]];
    SEL selector = NSSelectorFromString(setKeyPathsString);
    class_addMethod(myClass, selector, (IMP)setlinyiName, nil);
    // 3.改变isa 指针 ,第一个参数是原类，第二个是目标类
    object_setClass(self, myClass);
    // 4.保存观察者对象
    objc_setAssociatedObject(self, @"objc", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

void setlinyiName(id self,SEL _cmd,NSString *newName){
    //1.保存子类型
    id class = [self class];
    //2.改变 self 的 isa 指针
    object_setClass(self, class_getSuperclass(class));
    //3.调用父类的set方法
//    [NSString stringWithFormat:@"%@",_cmd]
    objc_msgSend(self, _cmd,newName);
    //4.拿到观察者,2020年04月11日17:15:50拿不到啊！
    id objc = objc_getAssociatedObject(self, @"objc");
    //5.通知观察者
    objc_msgSend(objc, @selector(observeValueForKeyPath:ofObject:change:context:),self,@"name",newName,nil);
    //6.改回子类类型
    object_setClass(self, class);
}
@end





